package com.media.module.fragment;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import com.droid.utils.BitmapHelper;
import com.droid.utils.Fileutils;
import com.droid.utils.ProgressDialogHelper;
import com.droid.utils.ProgressDialogHelper.ProgressCallBack;
import com.media.module.interfaces.CameraParamsChangedListener;
import com.media.module.interfaces.PhotoTakenCallback;
import com.media.module.interfaces.RawPhotoTakenCallback;
import com.media.module.model.CameraMode;
import com.media.module.model.FacingMode;
import com.media.module.model.FlashMode;
import com.media.module.model.FocusMode;
import com.media.module.model.HDRMode;
import com.media.module.model.Quality;
import com.media.module.model.Ratio;
import com.media.module.utils.ActivityStyle;
import com.media.module.utils.CameraUtils;
import com.media.module.utils.DimenValues;
import com.media.module.utils.MResource;
import com.media.module.utils.MediaConst;
import com.media.module.utils.UIGlobalDef;
import com.media.module.utils.VideoUtils;
import com.media.module.view.CameraPreview;
import com.media.module.view.FooterView;
import com.media.module.view.HeaderView;
import com.media.module.widget.RoundProgressBar;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.MediaScannerConnection;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OutputFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import timber.log.Timber;

/**
 * 
 * 录像
 * @author zhyc
 * 2016年7月20日下午5:03:45
 * TakeVideoFragment.java
 */
public class TakeVideoFragment extends BaseFragment implements OnClickListener,
	CameraParamsChangedListener,OnErrorListener {

	private final String TAG = "TakeVideoFragment";
	private static Context mContext;
	private ImageView mivCancel;
	private ImageView mivFlashLight;
	private ImageView mivCameraFacing;
	private ImageView mivOK;
	
	private ImageView mivStart;
	private ImageView mivPause;
	private ImageView mivResume;
	private ImageView mivStop;
	private TextView mtvTime;
	private ImageView mivPreviewVideo;
	private RoundProgressBar mrprbTime;
	
    public static final String QUALITY = "quality";
    public static final String RATIO = "ratio";
    public static final String FOCUS_MODE = "focus_mode";
    public static final String FLASH_MODE = "flash_mode";
    public static final String HDR_MODE = "hdr_mode";
    public static final String FRONT_CAMERA = "front_camera";
    private PhotoTakenCallback mCallback;
    private RawPhotoTakenCallback mRawCallback;
    private CameraParamsChangedListener mParamsChangedListener;
    private OrientationEventListener mOrientationListener;

    //录制视频的类
	private MediaRecorder mMediaRecorder;
	// 预缓存地址一
	private String mstrCurrentVideoFilePath = "";
	// 文件保存路径
	private String mstrSaveVideoFilePath = "";
	private ArrayList<String> marrVideoPath;
	
	//录制分辨率
	private int mintWidthPX = 640;
	private int mintHeightPX = 480;
	private int mintEncodingBitRate;
	CamcorderProfile mCamcorderProfile;
	
    private Quality mQuality;
    private Ratio mRatio;
    private FlashMode mFlashMode;
    private FacingMode mFacingMode;
    private FocusMode mFocusMode;
    private float mfBaseDimen;
    private int mintScreenWidth;
    private int mintScreenHeight;
    private int mNavigationBarHeight;
    private int mStatusBarHeight;
    private Map<Ratio, Camera.Size> mPreviewSizes;
    private Map<Ratio, Map<Quality, Camera.Size>> mPictureSizes;

    private Camera mCamera;
    private Camera.Parameters mParameters;
    private CameraPreview mCameraPreview;
    private ViewGroup mvContent;
    private HDRMode mHdrMode;
    private boolean mbSupportedHDR = false;
    private boolean mbSupportedFlash = false;

    private String mstrSaveVideoDirPath;
    private int mintCameraId;
    private int outputOrientation;
    
	// 当前时刻
	private long mThisTimes;
	// 记录时间
	private long mRecorderTime;
	// 录像时间最大值 默认30s
	private long mMaxTime = 0l;
	// 定时器
	private Timer mTimer;
	// 任务
	private TimerTask mTask;
	
	private final int INT_UPDATE_TAKE_TIME = 0x0001;
	private final int INT_STOP_UPDATE_VIEW = 0x0002;
    
    private Handler mHandler = new Handler(){
    	@Override
    	public void handleMessage(android.os.Message msg) {
    		switch (msg.what) {
			case INT_UPDATE_TAKE_TIME:
				if(mMaxTime == 0){ 
					mtvTime.setVisibility(View.VISIBLE);
					mtvTime.setText(CameraUtils.thisTime(mRecorderTime));
					mrprbTime.setProgress(0);
					mThisTimes = Calendar.getInstance().getTimeInMillis();
					break;
				}
				
				if (mRecorderTime <= mMaxTime) {
					mtvTime.setVisibility(View.VISIBLE);
					mtvTime.setText(CameraUtils.thisTime(mRecorderTime));
					int lintprogress = (int) Math.ceil((mRecorderTime) / (mMaxTime * 1.0) * 100);
					if (lintprogress > 0) {
						mrprbTime.setProgress(lintprogress);
					}
					mThisTimes = Calendar.getInstance().getTimeInMillis();
				} else {
					mivStop.performClick();

				}
				break;
			case INT_STOP_UPDATE_VIEW:
				mrprbTime.setProgress(0);
				if(mstrSaveVideoFilePath != null && !mstrSaveVideoFilePath.isEmpty()){
					mivPreviewVideo.setImageBitmap(BitmapHelper.getVideoThumbnail(mstrSaveVideoFilePath));
					MediaScannerConnection.scanFile(mContext, new String[] { mstrSaveVideoFilePath }, null,null);
				}
				break;
			default:
				break;
			}
    	}
    };

	public TakeVideoFragment(Context context, Bundle params) {
		mContext = context;
		setArguments(params);
	}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCamera = getCameraInstance(false);
        if (mCamera == null) {
            return;
        }
        initScreenParams();
        mParameters = mCamera.getParameters();
        mPreviewSizes = buildPreviewSizesRatioMap(mParameters.getSupportedPreviewSizes());
        mPictureSizes = buildPictureSizesRatioMap(mParameters.getSupportedPictureSizes());
        List<String> sceneModes = mParameters.getSupportedSceneModes();
        if (sceneModes != null) {
            for (String mode : sceneModes) {
                if (mode.equals(Camera.Parameters.SCENE_MODE_HDR)) {
                    mbSupportedHDR = true;
                    break;
                }
            }
        }
        //it returns false positive
        getActivity().getApplicationContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
        List<String> flashModes = mParameters.getSupportedFlashModes();
        if (flashModes == null || flashModes.size() <= 1) {  //Device has no flash 
            mbSupportedFlash = false;
        } else {
            mbSupportedFlash = true;
        }
        if (MediaConst.DEBUG) {
            Timber.d("PictureSizesRatioMap:");
            for (Ratio r : mPictureSizes.keySet()) {
                Timber.d(r.toString() + ":");
                for (Quality q : mPictureSizes.get(r).keySet()) {
                    Camera.Size size = mPictureSizes.get(r).get(q);
                    if (size != null) {
                        Timber.d(q.toString() + ": " + size.width + "x" + size.height);
                    }
                }
            }
        }
        expandParams(getArguments());
        initParams();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return getContentCameraView(mContext);
    }
    
    @Override
    public void onResume() {
        super.onResume();
        if (mCamera != null) {
            try {
                mCamera.reconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mOrientationListener == null) {
            initOrientationListener();
        }
        mOrientationListener.enable();
    }
    
    @Override
    public void onPause() {
        super.onPause();
        System.out.println("pause");
        if (mOrientationListener != null) {
            mOrientationListener.disable();
            mOrientationListener = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        cancel();
    }

    /**
	 * 构造用户界面
	 * @param context
	 * @return
	 */
	private View getContentCameraView(Context context) {
		DisplayMetrics displayMetrics = new DisplayMetrics();
	    activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

		mvContent = new RelativeLayout(context);
		mvContent.setBackgroundColor(Color.BLACK);
		mCameraPreview = new CameraPreview(mContext,mCamera);
		RelativeLayout.LayoutParams params = ActivityStyle.getContentCaneraLayoutParams();
        params.topMargin = mNavigationBarHeight;
        params.bottomMargin = mStatusBarHeight;
        mCameraPreview.setMisPixelsSet(false);
        mCameraPreview.setLayoutParams(params);
		
		// 增加画布
		mvContent.addView(mCameraPreview);
		
		// Top
		HeaderView llTop = new HeaderView(context);
		RelativeLayout.LayoutParams llTopLayoutParams = new RelativeLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, (int) (mfBaseDimen / 4 * 3));
		llTopLayoutParams.setMargins(0, ((int)MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, displayMetrics)), 0, 0);
		llTop.setOrientation(LinearLayout.HORIZONTAL);
		llTop.setLayoutParams(llTopLayoutParams);
		mvContent.addView(llTop);
		
		mtvTime = new TextView(mContext);
		mtvTime.setTextColor(Color.WHITE);
		mtvTime.setTextSize(((int)MResource.applyDimension(TypedValue.COMPLEX_UNIT_SP, 6, displayMetrics)));
		mtvTime.setEms(3);
		mtvTime.setGravity(Gravity.CENTER);
		mtvTime.setVisibility(View.GONE);

		mtvTime.setBackgroundColor(Color.argb(148, 148, 148, 148));
		RelativeLayout.LayoutParams lTVTimeParams = new RelativeLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		lTVTimeParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
		lTVTimeParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
		lTVTimeParams.bottomMargin = mStatusBarHeight;
		mtvTime.setLayoutParams(lTVTimeParams);
		mvContent.addView(mtvTime);
		
		// Bottom
		LinearLayout llBottom = new FooterView(context);
		RelativeLayout.LayoutParams llBottomLayoutParams = new RelativeLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, (int) (mfBaseDimen));
		llBottomLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
		llBottomLayoutParams.setMargins(0, 0, 0, ((int)MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, displayMetrics)));
		llBottom.setOrientation(LinearLayout.HORIZONTAL);
		llBottom.setGravity(Gravity.CENTER_VERTICAL);
		mvContent.addView(llBottom, llBottomLayoutParams);
		
		mivCancel = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CANCEL);
		mivCameraFacing = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CAMERA_FACING);
		mivFlashLight = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CAMERA_FLASH);
		mivOK = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.OK);

		mivStart = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.RECORD_MEDIA_START);
		mivPause = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.RECORD_MEDIA_PAUSE);
		mivResume = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.RECORD_MEDIA_RESUME);
		mivStop = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.RECORD_MEDIA_STOP);
		mivPreviewVideo = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.MEDIA_PREVIEW);
		mrprbTime = (RoundProgressBar) mvContent.findViewById(UIGlobalDef.VIEW_ID.ROUND_PROGRESS_BAR);
		
		mivCancel.setOnClickListener(this);
		mivCameraFacing.setOnClickListener(this);
		mivFlashLight.setOnClickListener(this);
		mivOK.setOnClickListener(this);
		
		mivStart.setOnClickListener(this);
		mivPause.setOnClickListener(this);
		mivResume.setOnClickListener(this);
		mivStop.setOnClickListener(this);
		mivPreviewVideo.setOnClickListener(this);
		return mvContent;
	}

	/**
	 * 设置控件Visible属性
	 * @param intStart 开始
	 * @param intPause 暂停
	 * @param intResume 唤醒
	 * @param intStop 停止
	 * @param intTime 录制时间
	 * @param intPreview 预览
	 * @param intProgress 进度
	 * @param intOk OK
	 */
	private void setControlVisible(int intStart, int intPause, int intResume, int intStop, 
			int intTime, int intPreview,int intProgress, int intOk){
		if(intStart >= 0){
			mivStart.setVisibility(intStart);
		}
		if(intPause >= 0){
			mivPause.setVisibility(intPause);
		}
		if(intResume >= 0){
			mivResume.setVisibility(intResume);
		}
		if(intStop >= 0){
			mivStop.setVisibility(intStop);
		}
		if(intTime >= 0){
			mtvTime.setVisibility(intTime);
		}
		if(intPreview >= 0){
			mivPreviewVideo.setVisibility(intPreview);
		}
		if(intOk >= 0){
			mivOK.setVisibility(intOk);
		}
	}
    /**
     * A safe way to get an instance of the Camera object.
     */
    private Camera getCameraInstance(boolean useFrontCamera) {
        Camera c = null;
        try {
            c = Camera.open(getCameraId(useFrontCamera));
        } catch (Exception e) {
            Timber.e(e, "Camera is not available (in use or does not exist).\nPlease close applications, that may use camera.");
        }
        return c;
    }

    private int getCameraId(boolean useFrontCamera) {
        int count = Camera.getNumberOfCameras();
        int result = -1;

        if (count > 0) {
            result = 0;

            Camera.CameraInfo info = new Camera.CameraInfo();
            for (int i = 0; i < count; i++) {
                Camera.getCameraInfo(i, info);

                if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK
                        && !useFrontCamera) {
                    result = i;
                    break;
                } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT
                        && useFrontCamera) {
                    result = i;
                    break;
                }
            }
        }
        mintCameraId = result;
        return result;
    }

    /**
     * 屏幕参数
     */
    private void initScreenParams() {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mintScreenWidth = displayMetrics.widthPixels;
        mintScreenHeight = displayMetrics.heightPixels;
        mfBaseDimen =  MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DimenValues.BASE_VALUE, displayMetrics);
        mNavigationBarHeight = (int) mfBaseDimen;
        mStatusBarHeight = (int) (mfBaseDimen * 1.2);
    }

    public void setCallback(PhotoTakenCallback callback) {
        this.mCallback = callback;
    }

    public void setRawCallback(RawPhotoTakenCallback rawCallback) {
        this.mRawCallback = rawCallback;
    }

    public void setParamsChangedListener(CameraParamsChangedListener paramsChangedListener) {
        this.mParamsChangedListener = paramsChangedListener;
    }

    private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {}
    };

    private Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            if (mRawCallback != null && data != null) {
                mRawCallback.rawPhotoTaken(data.clone());
            }
        }

    };

    /**
     * 录像
     * @param isResume
     */
    protected void takeVideo(boolean isResume) {
    	if (marrVideoPath == null) {
			marrVideoPath = new ArrayList<String>();
		}
    	if (!isResume) {
    		marrVideoPath.clear();
			mstrSaveVideoFilePath = "";
		}
		mstrCurrentVideoFilePath = mstrSaveVideoDirPath + getVideoFileName();
		if (mMediaRecorder == null) {
			mMediaRecorder = new MediaRecorder();
			mMediaRecorder.setOnErrorListener(this);
        } else {
        	mMediaRecorder.reset();
        }
		//Unlock and set camera to MediaRecorder
		mCamera.unlock();
		mMediaRecorder.setCamera(mCamera);
		// 设置录制视频源
		mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
		mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
		// 设置录制视频的输出格式THREE_GPP为3gp,MPEG_4为mp4
		mMediaRecorder.setOutputFormat(OutputFormat.MPEG_4);
		// 设置录制的视频编码H263, H264
		mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
		// 设置音频编码格式
		mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
		
		if(mCamcorderProfile == null){
			// 设置视频录制的分辨率。必须放在设置编码和格式的后面，否则报错
			mMediaRecorder.setVideoSize(mintWidthPX, mintHeightPX);
			// 设置高质量录制,改变编码位率
			mMediaRecorder.setVideoEncodingBitRate(mintEncodingBitRate == 0 ? 5 * 1024 * 512:mintEncodingBitRate);
			// 设置录制的视频帧率。必须放在设置编码和格式的后面，否则报错
			mMediaRecorder.setVideoFrameRate(30);
		}else{
			mMediaRecorder.setVideoSize(mCamcorderProfile.videoFrameWidth, mCamcorderProfile.videoFrameHeight);
			mMediaRecorder.setVideoEncodingBitRate(mintEncodingBitRate == 0 ? mCamcorderProfile.videoBitRate:mintEncodingBitRate);
			mMediaRecorder.setVideoFrameRate(mCamcorderProfile.videoFrameRate);
		}
		if(mFacingMode == FacingMode.FRONT && (outputOrientation == 90 || outputOrientation == 270)){
			mMediaRecorder.setOrientationHint(270);// 前置，摄像头，
		} else {
			mMediaRecorder.setOrientationHint(outputOrientation);// 后置摄像头
		}

		mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
		// 设置视频文件输出的路径
		mMediaRecorder.setOutputFile(mstrCurrentVideoFilePath);
		try {
			// 准备、开始
			mMediaRecorder.prepare();
			mMediaRecorder.start();// 开始刻录
			if (!isResume) {
				mRecorderTime = 0;
			}
			startTimerTask();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
    
    /**
     * 根据分辨率获取 CamcorderProfile
     * @param width 
     * @param height
     * @return
     */
    public CamcorderProfile getCamcorderProfile(int width, int height) {
		CamcorderProfile profile = null;
		String type = "";
		if( width == 3840 && height == 2160 ) {
			type = "4K Ultra HD ";
			profile = CamcorderProfile.get(mintCameraId, CamcorderProfile.QUALITY_HIGH);
			profile.videoFrameWidth = 3840;
			profile.videoFrameHeight = 2160;
			profile.videoBitRate = (int)(profile.videoBitRate*2.8); // need a higher bitrate for the better quality - this is roughly based on the bitrate used by an S5's native camera app at 4K (47.6 Mbps, compared to 16.9 Mbps which is what's returned by the QUALITY_HIGH profile)
		}
		else if( width == 1920 && height == 1080 ) {
			type = "Full HD ";
			profile = CamcorderProfile.get(mintCameraId,CamcorderProfile.QUALITY_1080P);
		}
		else if( width == 1280 && height == 720 ) {
			type = "HD ";
			profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
		}
		else if( width == 720 && height == 480 ) {
			type = "SD ";
			profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
		}
		else if( width == 640 && height == 480 ) {
			type = "VGA ";
		}
		else if( width == 352 && height == 288 ) {
			type = "CIF ";
			profile = CamcorderProfile.get(CamcorderProfile.QUALITY_CIF);
		}
		else if( width == 320 && height == 240 ) {
			type = "QVGA ";
			profile = CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
		}
		else if( width == 176 && height == 144 ) {
			type = "QCIF ";
			profile = CamcorderProfile.get(CamcorderProfile.QUALITY_QCIF);
		}
		return profile;
	}
    
    /**
     * 获取文件名
     * @return
     */
    private String getVideoFileName(){
    	return "VID_" + CameraUtils.getModifyTime()+".mp4";
    }

    /**
     * 启动任务计时
     */
	private void startTimerTask() {
		mThisTimes = Calendar.getInstance().getTimeInMillis();
		// 创建定时器
		mTimer = new Timer();
		mTask = new TimerTask() {
			@Override
			public void run() {
				mRecorderTime = mRecorderTime + (Calendar.getInstance().getTimeInMillis() - mThisTimes);
				mHandler.sendEmptyMessage(INT_UPDATE_TAKE_TIME);
			}
		};
		mTimer.schedule(mTask, 0, 1000); // 延时1000ms后执行，1000ms执行一次
	}

	/**
	 * 取消任务计时器
	 */
	private void cancelTimerTask() {
		if (mTimer != null) {
			mTimer.cancel();
			mTimer = null;
		}
		if (mTask != null) {
			mTask.cancel();
			mTask = null;
		}
	}
	
    /**
	 * 释放媒体资源
	 */
	private void releaseMedia() {
		if (mMediaRecorder != null) {
			try {
				mMediaRecorder.setOnErrorListener(null);
				mMediaRecorder.setPreviewDisplay(null);
				// 停止录制
				mMediaRecorder.stop();
				mMediaRecorder.reset();
				// 释放资源
				mMediaRecorder.release();
				mMediaRecorder = null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (mCamera != null) {
            try {
                mCamera.lock();
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
		cancelTimerTask();
	}
	
    private void expandParams(Bundle params) {
        if (params == null) {
            params = new Bundle();
        }
        if(params.containsKey(MediaConst.OUTPUT_VIDEO_PATH)){
        	mstrSaveVideoDirPath = params.getString(MediaConst.OUTPUT_VIDEO_PATH) + File.separator;
        	Fileutils.createDir(mstrSaveVideoDirPath);
        }
        if(params.containsKey(MediaConst.MEDIA_RECORD_MAX_TIME)){
        	mMaxTime = params.getInt(MediaConst.MEDIA_RECORD_MAX_TIME) * 1000l;
        }
        if(params.containsKey(MediaConst.OUTPUT_VIDEO_WIDTH_PX)){
        	mintWidthPX = params.getInt(MediaConst.OUTPUT_VIDEO_WIDTH_PX);
        }
        if(params.containsKey(MediaConst.OUTPUT_VIDEO_HEIGHT_PX)){
        	mintHeightPX = params.getInt(MediaConst.OUTPUT_VIDEO_HEIGHT_PX);
        }
        if(params.containsKey(MediaConst.VIDEO_ENCODING_BITRATE)){
        	mintEncodingBitRate = params.getInt(MediaConst.VIDEO_ENCODING_BITRATE);
        }
        int id = 0;
        if (params.containsKey(RATIO)) {
            id = params.getInt(RATIO, 1);
        }
        mRatio = Ratio.getRatioById(id);
        id = 0;
        if (params.containsKey(QUALITY)) {
            id = params.getInt(QUALITY, 0);
        }
        mQuality = Quality.getQualityById(id);
        id = 0;
        if (params.containsKey(FOCUS_MODE)) {
            id = params.getInt(FOCUS_MODE);
        }
        mFocusMode = FocusMode.getFocusModeById(id);
        id = 0;
        if (params.containsKey(FLASH_MODE)) {
            id = params.getInt(FLASH_MODE);
        }
        mFlashMode = FlashMode.getFlashModeById(id);
        id = 0;
        if (params.containsKey(HDR_MODE)) {
            id = params.getInt(HDR_MODE);
        }
        mHdrMode = HDRMode.getHDRModeById(id);
    }

    private void initParams() {
    	mCamcorderProfile = getCamcorderProfile(mintWidthPX, mintHeightPX);
    	mFlashMode = FlashMode.OFF;
    	mFacingMode = FacingMode.BACK;
    	setFlashMode(mParameters, mFlashMode);
        setPreviewSize(mParameters, mRatio);
        setHDRMode(mParameters, mHdrMode);
        setPictureSize(mParameters, mQuality, mRatio);
        mCamera.setParameters(mParameters);
    }
    
    @Override
    public void onQualityChanged(int id) {
        mQuality = Quality.getQualityById(id);
        setPictureSize(mParameters, mQuality, mRatio);
        mCamera.setParameters(mParameters);
        if (mParamsChangedListener != null) {
            mParamsChangedListener.onQualityChanged(id);
        }
    }

    @Override
    public void onRatioChanged(int id) {
        mRatio = Ratio.getRatioById(id);
        setPreviewSize(mParameters, mRatio);
        setPictureSize(mParameters, mQuality, mRatio);
        mCamera.setParameters(mParameters);
        setPreviewContainerSize(mintScreenWidth, mintScreenHeight, mRatio);
        if (mParamsChangedListener != null) {
            mParamsChangedListener.onRatioChanged(id);
        }
    }

    @Override
    public void onHDRChanged(int id) {
        mHdrMode = HDRMode.getHDRModeById(id);
        setHDRMode(mParameters, mHdrMode);
        mCamera.setParameters(mParameters);
        if (mParamsChangedListener != null) {
            mParamsChangedListener.onHDRChanged(id);
        }
    }

    @Override
    public void onFlashModeChanged(int id) {
        if (mParamsChangedListener != null) {
            mParamsChangedListener.onFlashModeChanged(id);
        }
    }

	private void switchFlashMode() {
		switch (mFlashMode) {
		case TOUCH:
			mFlashMode = FlashMode.OFF;
			break;
		case OFF:
			mFlashMode = FlashMode.TOUCH;
			break;
		default:
			break;
		}
		mParameters = mCameraPreview.getParameters();
		setFlashMode(mParameters, mFlashMode);
		mCamera.setParameters(mParameters);
	}
	
	private void switchFacingMode() {
		switch (mFacingMode) {
		case FRONT:
			mFacingMode = FacingMode.BACK;
			if(mbSupportedFlash){
				mivFlashLight.setVisibility(View.VISIBLE);
			}
			break;
		case BACK:
			mFacingMode = FacingMode.FRONT;
			mivFlashLight.setVisibility(View.GONE);
			break;
		default:
			break;
		}
		mCamera = mCameraPreview.switchFacingMode(mFacingMode);
	}

    private void setHDRMode(Camera.Parameters parameters, HDRMode hdrMode) {
        if (mbSupportedHDR && hdrMode == HDRMode.NONE) {
            hdrMode = HDRMode.OFF;
        }
        switch (hdrMode) {
            case ON:
                parameters.setSceneMode(Camera.Parameters.SCENE_MODE_HDR);
                break;
            case OFF:
                parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
                break;
		default:
			break;
        }
    }

    private void setFlashMode(Camera.Parameters parameters, FlashMode flashMode) {
        switch (flashMode) {
            case TOUCH:
            	parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
                break;
            case OFF:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                break;
		default:
			break;
        }
        setFlashModeImage(flashMode);
        
    }

    private void setFlashModeImage(FlashMode flashMode) {
    	if(mivFlashLight == null) return;
        switch (flashMode) {
            case TOUCH:
            	String[] strFlashOnLight = { "ic_btn_flash_always_on.png", "ic_btn_flash_always_on_pressed.png" };
            	mivFlashLight.setImageDrawable(MResource.getSelectorDrawable(mContext, strFlashOnLight));
                break;
            case OFF:
            	String[] strFlashOffLight = { "ic_btn_flash_torch_dark.png", "ic_btn_flash_torch_dark_pressed.png" };
            	mivFlashLight.setImageDrawable(MResource.getSelectorDrawable(mContext, strFlashOffLight));
                break;
		default:
			break;
        }
    }

    private void setPictureSize(Camera.Parameters parameters, Quality quality, Ratio ratio) {
        Camera.Size size = mPictureSizes.get(ratio).get(quality);
        if (size != null) {
            parameters.setPictureSize(size.width, size.height);
        }
    }

    private void setPreviewSize(Camera.Parameters parameters, Ratio ratio) {
        Camera.Size size = mPreviewSizes.get(ratio);
        parameters.setPreviewSize(size.width, size.height);
    }

    /**
     * @param width  Screen width
     * @param height Screen height
     * @param ratio  Required ratio
     */
    private void setPreviewContainerSize(int width, int height, Ratio ratio) {
        height = (width / ratio.h) * ratio.w;
        mvContent.setLayoutParams(new RelativeLayout.LayoutParams(width, height));
    }

    private Map<Ratio, Map<Quality, Camera.Size>> buildPictureSizesRatioMap(List<Camera.Size> sizes) {
        Map<Ratio, Map<Quality, Camera.Size>> map = new HashMap<Ratio, Map<Quality, Size>>();

        Map<Ratio, List<Camera.Size>> ratioListMap = new HashMap<Ratio, List<Size>>();
        for (Camera.Size size : sizes) {
            Ratio ratio = Ratio.pickRatio(size.width, size.height);
            if (ratio != null) {
                List<Camera.Size> sizeList = ratioListMap.get(ratio);
                if (sizeList == null) {
                    sizeList = new ArrayList<Size>();
                    ratioListMap.put(ratio, sizeList);
                }
                sizeList.add(size);
            }
        }
        for (Ratio r : ratioListMap.keySet()) {
            List<Camera.Size> list = ratioListMap.get(r);
            ratioListMap.put(r, sortSizes(list));
            Map<Quality, Camera.Size> sizeMap = new HashMap<Quality, Size>();
            int i = 0;
            for (Quality q : Quality.values()) {
                Camera.Size size = null;
                if (i < list.size()) {
                    size = list.get(i++);
                }
                sizeMap.put(q, size);
            }
            map.put(r, sizeMap);
        }

        return map;
    }

    private List<Camera.Size> sortSizes(List<Camera.Size> sizes) {
        int count = sizes.size();

        while (count > 2) {
            for (int i = 0; i < count - 1; i++) {
                Camera.Size current = sizes.get(i);
                Camera.Size next = sizes.get(i + 1);

                if (current.width < next.width || current.height < next.height) {
                    sizes.set(i, next);
                    sizes.set(i + 1, current);
                }
            }
            count--;
        }

        return sizes;
    }

    private Map<Ratio, Camera.Size> buildPreviewSizesRatioMap(List<Camera.Size> sizes) {
        Map<Ratio, Camera.Size> map = new HashMap<Ratio, Size>();

        for (Camera.Size size : sizes) {
            Ratio ratio = Ratio.pickRatio(size.width, size.height);
            if (ratio != null) {
                Camera.Size oldSize = map.get(ratio);
                if (oldSize == null || (oldSize.width < size.width || oldSize.height < size.height)) {
                    map.put(ratio, size);
                }
            }
        }
        return map;
    }

    private void initOrientationListener() {
        mOrientationListener = new OrientationEventListener(activity) {

            @Override
            public void onOrientationChanged(int orientation) {
                if (mCamera != null && orientation != ORIENTATION_UNKNOWN) {
                    int newOutputOrientation = getCameraPictureRotation(orientation);

                    if (newOutputOrientation != outputOrientation) {
                        outputOrientation = newOutputOrientation;

                        Camera.Parameters params = mCamera.getParameters();
                        params.setRotation(outputOrientation);
                        try {
                            mCamera.setParameters(params);
                        } catch (Exception e) {
                            Timber.e(e, "Exception updating camera parameters in orientation change");
                        }
                    }
                }
            }
        };
    }
    
    private int getCameraPictureRotation(int orientation) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mintCameraId, info);
        int rotation;
        orientation = (orientation + 45) / 90 * 90;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        	rotation = (info.orientation - orientation + 360) % 360;
        } else { // back-facing camera
        	rotation = (info.orientation + orientation) % 360;
        }
        return (rotation);
    }
    
	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case UIGlobalDef.VIEW_ID.CANCEL:
			cancel();
			getActivity().finish();
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_FACING:
			switchFacingMode();
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_FLASH:
			if (mbSupportedFlash) {
				switchFlashMode();
			}
			break;
		case UIGlobalDef.VIEW_ID.OK:
			Intent intent = getActivity().getIntent();
			intent.setData(Uri.fromFile(new File(mstrSaveVideoFilePath)));
			getActivity().setResult(Activity.RESULT_OK, intent);
			getActivity().finish();
			break;
		case UIGlobalDef.VIEW_ID.RECORD_MEDIA_START:
			setControlVisible(View.GONE, View.VISIBLE, View.GONE, View.VISIBLE, View.VISIBLE, View.GONE, View.VISIBLE,
					View.GONE);
			takeVideo(false);
			break;
		case UIGlobalDef.VIEW_ID.RECORD_MEDIA_PAUSE:
			setControlVisible(View.GONE, View.GONE, View.VISIBLE, View.GONE, -1, -1, -1, -1);
			releaseMedia();
			if(mstrCurrentVideoFilePath != null && !mstrCurrentVideoFilePath.isEmpty()){
				marrVideoPath.add(mstrCurrentVideoFilePath);
			}
			break;
		case UIGlobalDef.VIEW_ID.RECORD_MEDIA_RESUME:
			setControlVisible(-1, View.VISIBLE, View.GONE, View.VISIBLE, -1, -1, -1, -1);
			takeVideo(true);
			break;
		case UIGlobalDef.VIEW_ID.RECORD_MEDIA_STOP:
			setControlVisible(View.VISIBLE, View.GONE, View.GONE, View.GONE, View.GONE, View.VISIBLE, View.GONE,
					View.VISIBLE);
			releaseMedia();
			if(mstrCurrentVideoFilePath != null && !mstrCurrentVideoFilePath.isEmpty()){
				marrVideoPath.add(mstrCurrentVideoFilePath);
			}
			new ProgressDialogHelper(mContext).showProgressDialog("", MediaConst.MSG_LOADING, new ProgressCallBack() {

				@Override
				public void action() {
					String lstrFilePath = mstrSaveVideoDirPath + getVideoFileName();
					try {
						String[] strVideoPath = marrVideoPath.toArray(new String[0]);
						VideoUtils.appendVideo(mContext, lstrFilePath, strVideoPath);
						mstrSaveVideoFilePath = lstrFilePath;
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						for (int i = 0; i < marrVideoPath.size(); i++) {
							File tempFile = new File(marrVideoPath.get(i));
							if (tempFile.exists()) {
								tempFile.delete();
							}
						}
						marrVideoPath.clear();
						mHandler.sendEmptyMessage(INT_STOP_UPDATE_VIEW);
					}
				}
			});
			break;
		case UIGlobalDef.VIEW_ID.MEDIA_PREVIEW:
			Intent intentPlay = new Intent(android.content.Intent.ACTION_VIEW);
			Uri data = Uri.parse(mstrSaveVideoFilePath);
			intentPlay.setDataAndType(data, "video/mp4");
			startActivity(intentPlay);
			break;
		default:
			break;
		}
	}

	@Override
	public void onError(MediaRecorder mr, int what, int extra) {
		onError(mr,what, extra);
		try {
			if (mr != null)
				mr.reset();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
     * 取消录像
     */
	private void cancel() {
		releaseMedia();
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
		if (mOrientationListener != null) {
			mOrientationListener.disable();
			mOrientationListener = null;
		}
	}

	@Override
	public void onFocusModeChanged(int id) {
		// TODO Auto-generated method stub
		
	}
}
